﻿package src.uipackage.ui {
	
	import src.uipackage.ui.graphics.ComboOption;
	import flash.display.Sprite;
	import src.uipackage.ui.events.ComboBoxEvent;
	import src.uipackage.ui.graphics.ComboBoxGraphic;
	import flash.display.MovieClip;
	import flash.geom.Point;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
	import flash.text.AntiAliasType;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.events.Event;
	
	/**
	* UI widget combo box.
	* @author Devon O.
	*/
	public class OBO_ComboBox extends Sprite {
		
		private var _title:String;
		private var _initialText:String;
		private var _dp:Array;
		private var _boxWidth:int;
		private var _boxHeight:int;
		private var _displayFont:String;
		private var _displayFontSize:int;
		private var _optionFontSize:int;
		
		private var _titleText:TextField;
		private var _comboBox:ComboBoxGraphic;
		private var _selectedText:TextField;
		
		private var _choiceHolder:Sprite = new Sprite();
		private var _choices:Array = new Array();
		
		/**
		 * The OBO_ComboBox is UI widget for creating drop down combo boxes. The constructor should be passed an array of objects. Each object should contain a "label" property (which will be displayed in the combo box), and an associated "data" property (which will be returned by the ComboBoxEvent class).
		 * The OBO_ComboBox can also be used to create ComboBoxes displaying fonts. The Fonts should be embedded and an instance of each passed as the "data" property of each object in the dataprovider Array.
		 * @example The following example creates a combo box which displays two different types of fonts to choose from:
		 * <listing version="3.0">
		 * private function initComboBox():void {
		 * 		// BauhausFont and AvianFont are Font classes contained in .fla library.
		 *		var bf:Font = new BauhausFont();
		 *		var af:Font = new AvianFont();
		 *		var data:Array = [ { label:bf.fontName, data:bf }, { label:af.fontName, data:af } ];
		 *		_comboBox = new OBO_ComboBox("Fonts:", "- select font -", data, 120, 18, "_sans", 11, 22);
		 *		_comboBox.x = 50;
		 *		_comboBox.y = 50;
		 *		_comboBox.addEventListener(ComboBoxEvent.FONT_SELECTED, onComboSelect);
		 *		addChild(_comboBox);
		 *	}
		 *	
		 *	private function onComboSelect(cbe:ComboBoxEvent):void {
		 *		trace (cbe.data);	// will trace AvianFont or BauhausFont instance
		 *	}
		 * </listing>
		 * @param	title					The title which should be displayed for the combo box.
		 * @param	initialDisplayText		The initial text seen in the box.
		 * @param	dataProvider			An array of objects. Each object should contain a "label" property (String) and a "data" property (*).
		 * @param	width					Width of ComboBox box.
		 * @param	height					Height of ComboBox box.
		 * @param	displayFont				The name of the font to be used in the title and display text.
		 * @param	displayFontSize			The size of the font used in title and display text.
		 * @param	optionFontSize			The size of the font used in option display.
		 */
		public function OBO_ComboBox(title:String, initialDisplayText:String, dataProvider:Array, width:int = 120, height:int = 18, displayFont:String = "_sans", displayFontSize:int = 11, optionFontSize:int = 11):void {
			_title = title;
			_initialText = initialDisplayText;
			_dp = dataProvider;
			_boxWidth = width;
			_boxHeight = height;
			_displayFont = displayFont;
			_displayFontSize = displayFontSize;
			_optionFontSize = optionFontSize;
			
			init();
		}
		
		private function init():void {
			createTitle();
			createBox();
			createChoices();
		}
		
		private function createTitle():void {
			_titleText = new TextField();
			_titleText.autoSize = TextFieldAutoSize.LEFT;
			_titleText.selectable = false;
			_titleText.defaultTextFormat = new TextFormat(_displayFont, _displayFontSize);
			_titleText.antiAliasType = AntiAliasType.ADVANCED;
			_titleText.text = _title;
			addChild(_titleText);	
		}
		
		private function createBox():void {
			_comboBox = new ComboBoxGraphic(_boxWidth, _boxHeight);
			_comboBox.x = int(_titleText.width + 10);
			addChild(_comboBox);
			
			_selectedText = new TextField();
			_selectedText.width = _boxWidth - _boxHeight;
			_selectedText.height = _boxHeight - 2;
			_selectedText.selectable = false;
			_selectedText.mouseEnabled = false;
			_selectedText.defaultTextFormat = new TextFormat(_displayFont, _displayFontSize);
			_selectedText.antiAliasType = AntiAliasType.ADVANCED;
			_selectedText.background = true;
			_selectedText.text = _initialText;
			_selectedText.x = _comboBox.x + 1;
			_selectedText.y = _comboBox.y + 1;
			addChild(_selectedText);
			
			_comboBox.addEventListener(MouseEvent.CLICK, onClick);
		}
		
		private function createChoices():void {
			_dp.forEach(addChoice);
		}
		
		private function onOut(me:MouseEvent):void {
			removeChoices();
			_choices = new Array();
		}
		
		
		private function onClick(me:MouseEvent):void {
			addChoices();
		}
		
		private function onSelect(me:MouseEvent):void {
			_selectedText.text = me.target.label;
			dispatchEvent(new ComboBoxEvent(ComboBoxEvent.OPTION_SELECTED, me.target.data));
			removeChoices();
		}
		
		private function addChoices():void {
			parent.setChildIndex(this, parent.numChildren - 1);
			_choiceHolder.x = _comboBox.x;
			_choiceHolder.y = _comboBox.height;
			var gPoint:Point = localToGlobal(new Point(_choiceHolder.x, _choiceHolder.y));
			if ( (gPoint.y + _choiceHolder.height) >= stage.stageHeight)
				_choiceHolder.y = _comboBox.y - _choiceHolder.height;
			_choiceHolder.addEventListener(MouseEvent.ROLL_OUT, onOut);
			addChild(_choiceHolder);
		}
		
		private function addChoice(info:Object, i:int, a:Array):void {
			var c:ComboOption = new ComboOption(info.label, info.data, _comboBox.width, _optionFontSize);
			_choices.push(c);
			c.useHandCursor = false;
			if (i > 0) 
				c.y = _choices[i - 1].y + _choices[i - 1].height;
			c.addEventListener(MouseEvent.CLICK, onSelect);
			_choiceHolder.addChild(c);
		}
		
		
		private function removeChoices():void {
			if (contains(_choiceHolder)) removeChild(_choiceHolder);
		}
	}
}